package com.swu.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.swu.common.Result;
import com.swu.dto.MedicalRecordDTO;
import com.swu.dto.MedicalRecordQueryDTO;
import com.swu.vo.MedicalRecordVO;
import com.swu.mapper.*;
import com.swu.po.*;
import com.swu.service.MedicalRecordService;
import com.swu.service.MedicalRecordValidationService;
import com.swu.exception.BusinessException;
import com.swu.exception.PDFParseException;
import com.swu.exception.DataValidationException;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.text.PDFTextStripper;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer;

import java.io.IOException;
import java.io.StringWriter;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.function.Consumer;

@Slf4j
@Service
@RequiredArgsConstructor
public class MedicalRecordServiceImpl implements MedicalRecordService {

    private final FacilityInfoMapper facilityInfoMapper;
    private final PatientInfoMapper patientInfoMapper;
    private final AdmissionInfoMapper admissionInfoMapper;
    private final DiagnosisInfoMapper diagnosisInfoMapper;
    private final SurgeryInfoMapper surgeryInfoMapper;
    private final DischargeInfoMapper dischargeInfoMapper;
    private final BillingInfoMapper billingInfoMapper;
    private final MedicalTeamMapper medicalTeamMapper;
    private final MedicalRecordValidationService validationService;
    private final FreeMarkerConfigurer freeMarkerConfigurer;

    private static final Pattern DATE_PATTERN = Pattern.compile("(\\d{4})年(\\d{1,2})月(\\d{1,2})日");
    private static final Pattern DATETIME_PATTERN = Pattern.compile("(\\d{4})年(\\d{1,2})月(\\d{1,2})日\\s*(\\d{1,2})时(\\d{1,2})分");
    private static final Pattern MONEY_PATTERN = Pattern.compile("(\\d+(?:\\.\\d{1,2})?)");
    private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy年MM月dd日");
    private static final DateTimeFormatter DATETIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH时mm分");

    @Override
    public Page<MedicalRecordVO> queryMedicalRecords(MedicalRecordQueryDTO queryDTO) {
        // 1. 构建分页对象
        Page<PatientInfo> page = new Page<>(queryDTO.getPageNum(), queryDTO.getPageSize());

        // 2. 构建查询条件
        LambdaQueryWrapper<PatientInfo> wrapper = new LambdaQueryWrapper<>();
        
        // 2.1 患者姓名模糊查询
        if (StringUtils.hasText(queryDTO.getPatientName())) {
            wrapper.like(PatientInfo::getName, queryDTO.getPatientName());
        }
        
        // 2.2 病案号精确查询
        if (StringUtils.hasText(queryDTO.getMedicalRecordId())) {
            wrapper.eq(PatientInfo::getMedicalRecordId, queryDTO.getMedicalRecordId());
        }

        // 3. 查询患者基本信息
        Page<PatientInfo> patientInfoPage = patientInfoMapper.selectPage(page, wrapper);
        
        // 如果没有数据，直接返回空结果
        if (patientInfoPage.getRecords().isEmpty()) {
            return new Page<MedicalRecordVO>().setRecords(new ArrayList<>())
                    .setTotal(0)
                    .setCurrent(queryDTO.getPageNum())
                    .setSize(queryDTO.getPageSize());
        }

        // 4. 获取所有病案号
        List<String> medicalRecordIds = patientInfoPage.getRecords().stream()
                .map(PatientInfo::getMedicalRecordId)
                .collect(Collectors.toList());

        // 5. 批量查询关联信息
        // 5.1 查询住院信息
        LambdaQueryWrapper<AdmissionInfo> admissionWrapper = new LambdaQueryWrapper<AdmissionInfo>()
                .in(AdmissionInfo::getMedicalRecordId, medicalRecordIds);
        
        // 入院时间范围查询
        if (queryDTO.getAdmissionBeginTime() != null) {
            admissionWrapper.ge(AdmissionInfo::getAdmissionTime, 
                    LocalDateTime.of(queryDTO.getAdmissionBeginTime(), java.time.LocalTime.MIN));
        }
        if (queryDTO.getAdmissionEndTime() != null) {
            admissionWrapper.le(AdmissionInfo::getAdmissionTime, 
                    LocalDateTime.of(queryDTO.getAdmissionEndTime(), java.time.LocalTime.MAX));
        }
        
        List<AdmissionInfo> admissionInfos = admissionInfoMapper.selectList(admissionWrapper);
        Map<String, AdmissionInfo> admissionInfoMap = admissionInfos.stream()
                .collect(Collectors.toMap(AdmissionInfo::getMedicalRecordId, a -> a, (a1, a2) -> a1));

        // 5.2 查询主要诊断信息
        List<DiagnosisInfo> diagnosisInfos = diagnosisInfoMapper.selectList(
                new LambdaQueryWrapper<DiagnosisInfo>()
                        .in(DiagnosisInfo::getMedicalRecordId, medicalRecordIds)
                        .eq(DiagnosisInfo::getDiagnosisType, 1)); // 1-主要诊断
        Map<String, DiagnosisInfo> diagnosisInfoMap = diagnosisInfos.stream()
                .collect(Collectors.toMap(DiagnosisInfo::getMedicalRecordId, d -> d, (d1, d2) -> d1));

        // 5.3 查询医疗团队信息
        List<MedicalTeam> medicalTeams = medicalTeamMapper.selectList(
                new LambdaQueryWrapper<MedicalTeam>()
                        .in(MedicalTeam::getMedicalRecordId, medicalRecordIds));
        Map<String, MedicalTeam> medicalTeamMap = medicalTeams.stream()
                .collect(Collectors.toMap(MedicalTeam::getMedicalRecordId, m -> m, (m1, m2) -> m1));

        // 6. 组装返回结果
        List<MedicalRecordVO> resultList = patientInfoPage.getRecords().stream()
                .map(patientInfo -> {
                    MedicalRecordVO vo = new MedicalRecordVO();
                    
                    // 6.1 设置患者信息
                    MedicalRecordVO.PatientInfoVO patientInfoVO = new MedicalRecordVO.PatientInfoVO();
                    patientInfoVO.setMedicalRecordId(patientInfo.getMedicalRecordId());
                    patientInfoVO.setName(patientInfo.getName());
                    patientInfoVO.setGender(patientInfo.getGender());
                    patientInfoVO.setAge(patientInfo.getAge());
                    patientInfoVO.setIdNumber(patientInfo.getIdNumber());
                    vo.setPatientInfo(patientInfoVO);
                    
                    // 6.2 设置住院信息
                    AdmissionInfo admissionInfo = admissionInfoMap.get(patientInfo.getMedicalRecordId());
                    if (admissionInfo != null) {
                        MedicalRecordVO.AdmissionInfoVO admissionInfoVO = new MedicalRecordVO.AdmissionInfoVO();
                        admissionInfoVO.setAdmissionId(admissionInfo.getAdmissionId());
                        admissionInfoVO.setAdmissionTime(admissionInfo.getAdmissionTime());
                        admissionInfoVO.setAdmissionDept(admissionInfo.getAdmissionDept());
                        admissionInfoVO.setActualDays(admissionInfo.getActualDays());
                        vo.setAdmissionInfo(admissionInfoVO);
                    }
                    
                    // 6.3 设置诊断信息
                    DiagnosisInfo diagnosisInfo = diagnosisInfoMap.get(patientInfo.getMedicalRecordId());
                    if (diagnosisInfo != null) {
                        MedicalRecordVO.DiagnosisInfoVO diagnosisInfoVO = new MedicalRecordVO.DiagnosisInfoVO();
                        diagnosisInfoVO.setMainDiagnosis(diagnosisInfo.getDiagnosisName());
                        diagnosisInfoVO.setMainDiagCode(diagnosisInfo.getDiagCode());
                        vo.setDiagnosisInfo(diagnosisInfoVO);
                    }
                    
                    // 6.4 设置医疗团队信息
                    MedicalTeam medicalTeam = medicalTeamMap.get(patientInfo.getMedicalRecordId());
                    if (medicalTeam != null) {
                        MedicalRecordVO.MedicalTeamVO medicalTeamVO = new MedicalRecordVO.MedicalTeamVO();
                        medicalTeamVO.setQualityGrade(medicalTeam.getQualityGrade());
                        medicalTeamVO.setQcDate(LocalDateTime.of(medicalTeam.getQcDate(), java.time.LocalTime.MIN));
                        vo.setMedicalTeam(medicalTeamVO);
                    }
                    
                    return vo;
                })
                .collect(Collectors.toList());

        // 7. 返回分页结果
        return new Page<MedicalRecordVO>()
                .setRecords(resultList)
                .setTotal(patientInfoPage.getTotal())
                .setCurrent(patientInfoPage.getCurrent())
                .setSize(patientInfoPage.getSize());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result<String> processMedicalRecordPdf(MultipartFile file) {
        if (file == null || file.isEmpty()) {
            throw new BusinessException("请选择要上传的PDF文件");
        }

        if (!file.getOriginalFilename().toLowerCase().endsWith(".pdf")) {
            throw new BusinessException("只支持PDF格式文件");
        }

        try {
            // 1. 读取PDF文件
            PDDocument document = PDDocument.load(file.getInputStream());
            PDFTextStripper stripper = new PDFTextStripper();
            String text = stripper.getText(document);
            document.close();

            // 2. 解析PDF内容
            MedicalRecordDTO recordDTO = parsePdfContent(text);

            // 3. 检查病案号是否已存在
            PatientInfo existingPatient = patientInfoMapper.selectById(recordDTO.getMedicalRecordId());
            if (existingPatient != null) {
                throw new BusinessException("病案号 " + recordDTO.getMedicalRecordId() + " 已存在");
            }

            // 4. 保存解析后的数据
            String medicalRecordId = saveMedicalRecord(recordDTO);

            return Result.success(medicalRecordId);
        } catch (IOException e) {
            log.error("处理PDF文件失败", e);
            throw new PDFParseException("PDF文件处理失败：" + e.getMessage(), e);
        } catch (BusinessException e) {
            throw e;
        } catch (Exception e) {
            log.error("处理病案数据失败", e);
            throw new BusinessException("处理病案数据失败：" + e.getMessage(), e);
        }
    }

    private MedicalRecordDTO parsePdfContent(String content) {
        MedicalRecordDTO dto = new MedicalRecordDTO();
        
        try {
            // 1. 提取病案号（这是必须的第一步）
            String medicalRecordId = extractMedicalRecordId(content);
            if (medicalRecordId == null || medicalRecordId.trim().isEmpty()) {
                throw new PDFParseException("未能从PDF中提取到病案号");
            }
            dto.setMedicalRecordId(medicalRecordId);

            // 2. 医疗机构信息
            extractFacilityInfo(content, dto);
            
            // 2. 患者基本信息
            extractPatientInfo(content, dto);
            
            // 3. 住院信息
            extractAdmissionInfo(content, dto);
            
            // 4. 诊断信息
            extractDiagnosisInfo(content, dto);
            
            // 5. 出院信息
            extractDischargeInfo(content, dto);
            
            // 6. 费用信息
            extractBillingInfo(content, dto);
            
            // 7. 医疗团队信息
            extractMedicalTeamInfo(content, dto);
            
            return dto;
        } catch (Exception e) {
            log.error("解析PDF内容失败", e);
            throw new PDFParseException("解析PDF内容失败: " + e.getMessage(), e);
        }
    }

    private String extractMedicalRecordId(String content) {
        // 尝试多种可能的格式
        String[] patterns = {
            "病案号[：:](\\S+)",
            "病历号[：:](\\S+)",
            "病案号码[：:](\\S+)",
            "病历号码[：:](\\S+)"
        };

        for (String patternStr : patterns) {
            Pattern pattern = Pattern.compile(patternStr);
            Matcher matcher = pattern.matcher(content);
            if (matcher.find()) {
                return matcher.group(1).trim();
            }
        }

        return null;
    }

    private void extractFacilityInfo(String content, MedicalRecordDTO dto) {
        // 提取医疗机构名称
        extractByPattern(content, "医疗机构[：:](.*?)(?=\\s|$)", dto::setOrgName);
        
        // 提取组织机构编码
        extractByPattern(content, "组织机构编码[：:](.*?)(?=\\s|$)", dto::setOrgCode);
    }

    private void extractPatientInfo(String content, MedicalRecordDTO dto) {
        // 基本信息
        extractByPattern(content, "姓名[：:](.*?)(?=\\s|性别|$)", dto::setName);
        extractByPattern(content, "性别[：:](.*?)(?=\\s|$)", dto::setGender);
        extractByPattern(content, "国籍[：:](.*?)(?=\\s|$)", dto::setNationality);
        extractByPattern(content, "民族[：:](.*?)(?=\\s|$)", dto::setEthnicity);
        extractByPattern(content, "出生地[：:](.*?)(?=\\s|$)", dto::setBirthPlace);
        extractByPattern(content, "籍贯[：:](.*?)(?=\\s|$)", dto::setOriginPlace);
        
        // 证件信息
        extractByPattern(content, "证件号码[：:](.*?)(?=\\s|$)", dto::setIdNumber);
        extractByPattern(content, "健康卡号[：:](.*?)(?=\\s|$)", dto::setHealthCard);
        
        // 出生日期和年龄
        extractDate(content, "出生日期[：:]", dto::setBirthDate);
        extractInteger(content, "年龄[：:](\\d+)岁", dto::setAge);
        extractInteger(content, "月龄[：:](\\d+)月", dto::setInfantAgeMonths);
        
        // 联系信息
        extractByPattern(content, "现住址[：:](.*?)(?=\\s|$)", dto::setCurrentAddress);
        extractByPattern(content, "电话[：:](.*?)(?=\\s|$)", dto::setPhone);
        extractByPattern(content, "邮编[：:](\\d{6})", dto::setPostalCode);
        extractByPattern(content, "户口地址[：:](.*?)(?=\\s|$)", dto::setRegisteredAddress);
        extractByPattern(content, "工作单位[：:](.*?)(?=\\s|$)", dto::setWorkUnit);
        extractByPattern(content, "单位电话[：:](.*?)(?=\\s|$)", dto::setWorkPhone);
        
        // 联系人信息
        extractByPattern(content, "联系人姓名[：:](.*?)(?=\\s|$)", dto::setContactName);
        extractByPattern(content, "联系人关系[：:](.*?)(?=\\s|$)", dto::setContactRelation);
        extractByPattern(content, "联系人电话[：:](.*?)(?=\\s|$)", dto::setContactPhone);
        
        // 特殊信息
        extractInteger(content, "血型[：:](\\d)", dto::setBloodType);
        extractInteger(content, "Rh因子[：:](\\d)", dto::setRhFactor);
        extractInteger(content, "婚姻状况[：:](\\d)", dto::setMaritalStatus);
    }

    private void extractAdmissionInfo(String content, MedicalRecordDTO dto) {
        // 住院基本信息
        extractInteger(content, "第(\\d+)次住院", dto::setAdmissionCount);
        extractInteger(content, "医疗付费方式[：:](\\d)", dto::setPaymentMethod);
        extractInteger(content, "入院途径[：:](\\d)", dto::setAdmissionPath);
        
        // 入院信息
        extractDateTime(content, "入院时间[：:]", dto::setAdmissionTime);
        extractByPattern(content, "入院科别[：:](.*?)(?=\\s|$)", dto::setAdmissionDept);
        extractByPattern(content, "病房[：:](.*?)(?=\\s|$)", dto::setWard);
        
        // 转科信息
        extractByPattern(content, "转科科别[：:](.*?)(?=\\s|$)", dto::setTransferDept);
        
        // 出院信息
        extractDateTime(content, "出院时间[：:]", dto::setDischargeTime);
        extractByPattern(content, "出院科别[：:](.*?)(?=\\s|$)", dto::setDischargeDept);
        extractInteger(content, "实际住院天数[：:](\\d+)", dto::setActualDays);
        
        // 诊断信息
        extractByPattern(content, "门\\(急\\)诊诊断[：:](.*?)(?=\\s|$)", dto::setErDiagnosis);
        extractByPattern(content, "门诊疾病编码[：:](.*?)(?=\\s|$)", dto::setErDiagCode);
    }

    private void extractDiagnosisInfo(String content, MedicalRecordDTO dto) {
        // 主要诊断
        extractByPattern(content, "主要诊断[：:](.*?)(?=\\s|其他诊断|$)", dto::setMainDiagnosis);
        extractByPattern(content, "主要诊断疾病编码[：:](.*?)(?=\\s|$)", dto::setMainDiagnosisCode);
        extractInteger(content, "入院病情[：:](\\d)", dto::setMainDiagnosisStatus);
    }

    private void extractDischargeInfo(String content, MedicalRecordDTO dto) {
        // 离院信息
        extractInteger(content, "离院方式[：:](\\d)", dto::setDischargeMethod);
        extractByPattern(content, "拟接收机构[：:](.*?)(?=\\s|$)", dto::setReceivingOrg);
        
        // 再住院计划
        extractInteger(content, "31天再住院计划[：:](\\d)", dto::setReadmissionPlan);
        extractByPattern(content, "再住院目的[：:](.*?)(?=\\s|$)", dto::setReadmissionReason);
    }

    private void extractBillingInfo(String content, MedicalRecordDTO dto) {
        // 总费用信息
        extractMoney(content, "总费用[：:](.*?)元", dto::setTotalCost);
        extractMoney(content, "自付金额[：:](.*?)元", dto::setSelfPay);
        
        // 一般医疗服务费用
        extractMoney(content, "一般医疗服务费[：:](.*?)元", dto::setGeneralMedicalService);
        extractMoney(content, "一般治疗操作费[：:](.*?)元", dto::setGeneralTreatmentOperation);
        extractMoney(content, "护理费[：:](.*?)元", dto::setNursingFee);
        
        // 诊断费用
        extractMoney(content, "病理诊断费[：:](.*?)元", dto::setPathologyDiagnosis);
        extractMoney(content, "实验室诊断费[：:](.*?)元", dto::setLaboratoryDiagnosis);
        extractMoney(content, "影像学诊断费[：:](.*?)元", dto::setImagingDiagnosis);
        extractMoney(content, "临床诊断项目费[：:](.*?)元", dto::setClinicalDiagnosis);
        
        // 治疗费用
        extractMoney(content, "非手术治疗项目费[：:](.*?)元", dto::setNonSurgicalTreatment);
        extractMoney(content, "手术治疗费[：:](.*?)元", dto::setSurgicalTreatment);
        extractMoney(content, "康复费[：:](.*?)元", dto::setRehabilitation);
        extractMoney(content, "中医治疗费[：:](.*?)元", dto::setTcmTreatment);
        
        // 药品费用
        extractMoney(content, "西药费[：:](.*?)元", dto::setWesternMedicine);
        extractMoney(content, "中成药费[：:](.*?)元", dto::setChinesePatentMedicine);
        extractMoney(content, "中草药费[：:](.*?)元", dto::setChineseHerbalMedicine);
        
        // 血液和制品费用
        extractMoney(content, "血费[：:](.*?)元", dto::setBloodFee);
        extractMoney(content, "白蛋白类制品费[：:](.*?)元", dto::setAlbumin);
        extractMoney(content, "球蛋白类制品费[：:](.*?)元", dto::setGlobulin);
        
        // 医用材料费
        extractMoney(content, "检查用一次性医用材料费[：:](.*?)元", dto::setDisposableExamMaterials);
        extractMoney(content, "治疗用一次性医用材料费[：:](.*?)元", dto::setDisposableTreatMaterials);
        extractMoney(content, "手术用一次性医用材料费[：:](.*?)元", dto::setDisposableSurgeryMaterials);
        
        // 其他费用
        extractMoney(content, "其他费用[：:](.*?)元", dto::setOtherCosts);
    }

    private void extractMedicalTeamInfo(String content, MedicalRecordDTO dto) {
        // 医生信息
        extractByPattern(content, "科主任[：:](.*?)(?=\\s|$)", dto::setDepartmentHead);
        extractByPattern(content, "主治医师[：:](.*?)(?=\\s|$)", dto::setAttending);
        extractByPattern(content, "住院医师[：:](.*?)(?=\\s|$)", dto::setResident);
        
        // 护士信息
        extractByPattern(content, "责任护士[：:](.*?)(?=\\s|$)", dto::setNurse);
        
        // 质控信息
        extractInteger(content, "病案质量等级[：:](\\d)", dto::setQualityGrade);
        extractByPattern(content, "质控医师[：:](.*?)(?=\\s|$)", dto::setQcDoctor);
        extractByPattern(content, "质控护士[：:](.*?)(?=\\s|$)", dto::setQcNurse);
        extractDate(content, "质控日期[：:]", dto::setQcDate);
    }

    // 工具方法
    private void extractByPattern(String content, String pattern, Consumer<String> setter) {
        Pattern p = Pattern.compile(pattern);
        Matcher m = p.matcher(content);
        if (m.find()) {
            setter.accept(m.group(1).trim());
        }
    }

    private void extractInteger(String content, String pattern, Consumer<Integer> setter) {
        Pattern p = Pattern.compile(pattern);
        Matcher m = p.matcher(content);
        if (m.find()) {
            try {
                setter.accept(Integer.parseInt(m.group(1)));
            } catch (NumberFormatException e) {
                log.warn("解析整数失败: {}", m.group(1));
            }
        }
    }

    private void extractDate(String content, String prefix, Consumer<LocalDate> setter) {
        Pattern p = Pattern.compile(prefix + DATE_PATTERN);
        Matcher m = p.matcher(content);
        if (m.find()) {
            try {
                int year = Integer.parseInt(m.group(1));
                int month = Integer.parseInt(m.group(2));
                int day = Integer.parseInt(m.group(3));
                setter.accept(LocalDate.of(year, month, day));
            } catch (Exception e) {
                log.warn("解析日期失败: {}", m.group());
            }
        }
    }

    private void extractDateTime(String content, String prefix, Consumer<LocalDateTime> setter) {
        Pattern p = Pattern.compile(prefix + DATETIME_PATTERN);
        Matcher m = p.matcher(content);
        if (m.find()) {
            try {
                int year = Integer.parseInt(m.group(1));
                int month = Integer.parseInt(m.group(2));
                int day = Integer.parseInt(m.group(3));
                int hour = Integer.parseInt(m.group(4));
                int minute = Integer.parseInt(m.group(5));
                setter.accept(LocalDateTime.of(year, month, day, hour, minute));
            } catch (Exception e) {
                log.warn("解析日期时间失败: {}", m.group());
            }
        }
    }

    private void extractMoney(String content, String pattern, Consumer<BigDecimal> setter) {
        Pattern p = Pattern.compile(pattern);
        Matcher m = p.matcher(content);
        if (m.find()) {
            try {
                Matcher moneyMatcher = MONEY_PATTERN.matcher(m.group(1));
                if (moneyMatcher.find()) {
                    setter.accept(new BigDecimal(moneyMatcher.group(1)));
                }
            } catch (Exception e) {
                log.warn("解析金额失败: {}", m.group(1));
            }
        }
    }

    @Transactional(rollbackFor = Exception.class)
    public String saveMedicalRecord(@Valid MedicalRecordDTO recordDTO) {
        try {
            // 1. 使用PDF中提取的病案号
            String medicalRecordId = recordDTO.getMedicalRecordId();

            // 2. 保存医疗机构信息
            FacilityInfo facilityInfo = facilityInfoMapper.selectById(recordDTO.getOrgCode());
            if (facilityInfo == null) {
                facilityInfo = new FacilityInfo();
                facilityInfo.setOrgName(recordDTO.getOrgName());
                facilityInfo.setOrgCode(recordDTO.getOrgCode());
                facilityInfoMapper.insert(facilityInfo);
            }

            // 3. 保存患者基本信息
            PatientInfo patientInfo = new PatientInfo();
            patientInfo.setMedicalRecordId(medicalRecordId);
            patientInfo.setName(recordDTO.getName());
            patientInfo.setGender(recordDTO.getGender());
            patientInfo.setBirthDate(recordDTO.getBirthDate());
            patientInfo.setAge(recordDTO.getAge());
            patientInfo.setNationality(recordDTO.getNationality());
            patientInfo.setBirthPlace(recordDTO.getBirthPlace());
            patientInfo.setOriginPlace(recordDTO.getOriginPlace());
            patientInfo.setEthnicity(recordDTO.getEthnicity());
            patientInfo.setIdNumber(recordDTO.getIdNumber());
            patientInfo.setOccupation(recordDTO.getOccupation());
            patientInfo.setMaritalStatus(recordDTO.getMaritalStatus());
            patientInfo.setCurrentAddress(recordDTO.getCurrentAddress());
            patientInfo.setPhone(recordDTO.getPhone());
            patientInfo.setPostalCode(recordDTO.getPostalCode());
            patientInfo.setRegisteredAddress(recordDTO.getRegisteredAddress());
            patientInfo.setWorkUnit(recordDTO.getWorkUnit());
            patientInfo.setWorkPhone(recordDTO.getWorkPhone());
            patientInfo.setContactName(recordDTO.getContactName());
            patientInfo.setContactRelation(recordDTO.getContactRelation());
            patientInfo.setContactPhone(recordDTO.getContactPhone());
            patientInfo.setBloodType(recordDTO.getBloodType());
            patientInfo.setRhFactor(recordDTO.getRhFactor());
            patientInfo.setFacilityOrgCode(facilityInfo.getOrgCode());
            patientInfoMapper.insert(patientInfo);

            // 4. 保存住院信息
            AdmissionInfo admissionInfo = new AdmissionInfo();
            admissionInfo.setMedicalRecordId(medicalRecordId);
            admissionInfo.setAdmissionCount(recordDTO.getAdmissionCount());
            admissionInfo.setPaymentMethod(recordDTO.getPaymentMethod());
            admissionInfo.setAdmissionPath(recordDTO.getAdmissionPath());
            admissionInfo.setAdmissionTime(recordDTO.getAdmissionTime());
            admissionInfo.setAdmissionDept(recordDTO.getAdmissionDept());
            admissionInfo.setWard(recordDTO.getWard());
            admissionInfo.setTransferDept(recordDTO.getTransferDept());
            admissionInfo.setDischargeTime(recordDTO.getDischargeTime());
            admissionInfo.setDischargeDept(recordDTO.getDischargeDept());
            admissionInfo.setActualDays(recordDTO.getActualDays());
            admissionInfo.setErDiagnosis(recordDTO.getErDiagnosis());
            admissionInfo.setErDiagCode(recordDTO.getErDiagCode());
            admissionInfoMapper.insert(admissionInfo);

            // 5. 保存诊断信息
            DiagnosisInfo diagnosisInfo = new DiagnosisInfo();
            diagnosisInfo.setMedicalRecordId(medicalRecordId);
            diagnosisInfo.setDiagnosisType(1); // 主要诊断
            diagnosisInfo.setDiagnosisName(recordDTO.getMainDiagnosis());
            diagnosisInfo.setDiagCode(recordDTO.getMainDiagnosisCode());
            diagnosisInfo.setAdmissionStatus(recordDTO.getMainDiagnosisStatus());
            diagnosisInfoMapper.insert(diagnosisInfo);

            // 6. 保存出院信息
            DischargeInfo dischargeInfo = new DischargeInfo();
            dischargeInfo.setMedicalRecordId(medicalRecordId);
            dischargeInfo.setDischargeMethod(recordDTO.getDischargeMethod());
            dischargeInfo.setReceivingOrg(recordDTO.getReceivingOrg());
            dischargeInfo.setReadmissionPlan(recordDTO.getReadmissionPlan());
            dischargeInfo.setReadmissionReason(recordDTO.getReadmissionReason());
            dischargeInfoMapper.insert(dischargeInfo);

            // 7. 保存医疗团队信息
            MedicalTeam medicalTeam = new MedicalTeam();
            medicalTeam.setMedicalRecordId(medicalRecordId);
            medicalTeam.setDepartmentHead(recordDTO.getDepartmentHead());
            medicalTeam.setAttending(recordDTO.getAttending());
            medicalTeam.setResident(recordDTO.getResident());
            medicalTeam.setNurse(recordDTO.getNurse());
            medicalTeam.setQualityGrade(recordDTO.getQualityGrade());
            medicalTeam.setQcDoctor(recordDTO.getQcDoctor());
            medicalTeam.setQcNurse(recordDTO.getQcNurse());
            medicalTeam.setQcDate(recordDTO.getQcDate());
            medicalTeamMapper.insert(medicalTeam);

            return medicalRecordId;
        } catch (Exception e) {
            log.error("保存病案数据失败", e);
            throw new DataValidationException("保存病案数据失败: " + e.getMessage(), e);
        }
    }

    @Override
    public Map<String, Object> getMedicalRecordDetailHtml(String medicalRecordId) {
        if (!StringUtils.hasText(medicalRecordId)) {
            throw new BusinessException("病案号不能为空");
        }

        // 1. 校验病案数据
        Result<List<String>> validationResult = validationService.validate(medicalRecordId);
        List<String> validationErrors = validationResult.getData() != null ? validationResult.getData() : new ArrayList<>();

        // 2. 获取病案所有相关数据
        PatientInfo patientInfo = patientInfoMapper.selectById(medicalRecordId);
        if (patientInfo == null) {
            throw new BusinessException("病案不存在: " + medicalRecordId);
        }

        List<DiagnosisInfo> diagnosisList = diagnosisInfoMapper.selectList(
                new LambdaQueryWrapper<DiagnosisInfo>()
                        .eq(DiagnosisInfo::getMedicalRecordId, medicalRecordId)
        );

        AdmissionInfo admissionInfo = admissionInfoMapper.selectOne(
                new LambdaQueryWrapper<AdmissionInfo>()
                        .eq(AdmissionInfo::getMedicalRecordId, medicalRecordId)
        );

        SurgeryInfo surgeryInfo = surgeryInfoMapper.selectOne(
                new LambdaQueryWrapper<SurgeryInfo>()
                        .eq(SurgeryInfo::getMedicalRecordId, medicalRecordId)
        );

        DischargeInfo dischargeInfo = dischargeInfoMapper.selectOne(
                new LambdaQueryWrapper<DischargeInfo>()
                        .eq(DischargeInfo::getMedicalRecordId, medicalRecordId)
        );

        BillingInfo billingInfo = billingInfoMapper.selectOne(
                new LambdaQueryWrapper<BillingInfo>()
                        .eq(BillingInfo::getMedicalRecordId, medicalRecordId)
        );

        MedicalTeam medicalTeam = medicalTeamMapper.selectOne(
                new LambdaQueryWrapper<MedicalTeam>()
                        .eq(MedicalTeam::getMedicalRecordId, medicalRecordId)
        );

        FacilityInfo facilityInfo = facilityInfoMapper.selectById(patientInfo.getFacilityOrgCode());

        // 3. 创建数据模型
        Map<String, Object> model = new HashMap<>();
        model.put("facilityInfo", facilityInfo);
        model.put("patientInfo", patientInfo);
        model.put("admissionInfo", admissionInfo);
        model.put("diagnosisList", diagnosisList);
        model.put("surgeryInfo", surgeryInfo);
        model.put("dischargeInfo", dischargeInfo);
        model.put("billingInfo", billingInfo);
        model.put("medicalTeam", medicalTeam);
        model.put("validationErrors", validationErrors);
        
        return model;
    }
} 